package com.rslai.base.tool.servertest.dsl;

import com.rslai.base.tool.servertest.annotation.Element;
import com.rslai.base.tool.servertest.command.StepCommand;
import com.rslai.base.tool.servertest.config.StepConfig;
import com.rslai.base.tool.servertest.model.KeyValueStore;
import com.rslai.base.tool.servertest.util.CloneUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;

public class DSLCommandConfig extends StepConfig
        implements Cloneable {
    private static Map<String, DSLCommandDesc> DSLMAPPING = new HashMap();

    @Element
    List<KeyValueStore> params;

    public static void map(String commandName, DSLCommandDesc dslCommandDesc) {
        DSLMAPPING.put(commandName, dslCommandDesc);
    }


    public StepCommand createCommand() {
        DSLCommandDesc dslCommandDesc = (DSLCommandDesc) DSLMAPPING.get(this.commandName);
        if ((dslCommandDesc == null) && (!"data".equalsIgnoreCase(this.commandName))) {
            throw new RuntimeException("未定义的DSL命令: " + this.commandName);
        }
        List commands = createCommands(dslCommandDesc.children(), false, false);
        return new DSLCommand((DSLCommandDesc) dslCommandDesc.clone(), CloneUtil.cloneKeyValueStore(this.params), commands);
    }

    public StepCommand createCommand(boolean follow, boolean beFollowed) {
        DSLCommandDesc dslCommandDesc = (DSLCommandDesc) DSLMAPPING.get(this.commandName);
        if ((dslCommandDesc == null) && (!"data".equalsIgnoreCase(this.commandName))) {
            throw new RuntimeException("未定义的DSL命令: " + this.commandName);
        }
        List commands = createCommands(dslCommandDesc.children(), follow, beFollowed);
        return new DSLCommand((DSLCommandDesc) dslCommandDesc.clone(), CloneUtil.cloneKeyValueStore(this.params), commands);
    }

    private List<StepCommand> createCommands(List<StepConfig> stepConfigs, boolean follow, boolean beFollowed) {
        List commands = new ArrayList();
        for (StepConfig config : stepConfigs)
            if ((!"data".equalsIgnoreCase(config.getCommandName())) &&
                    ((!(config instanceof DSLCommandConfig)) || (!follow) || (!checkFollow(((DSLCommandConfig) config).params, "notRunWhenFollow"))) && (
                    (!(config instanceof DSLCommandConfig)) || (!beFollowed) || (!checkFollow(((DSLCommandConfig) config).params, "notRunWhenBeFollowed")))) {
                StepCommand command = null;
                if ((config instanceof DSLCommandConfig))
                    command = ((DSLCommandConfig) config).createCommand(follow, beFollowed).cloneCommand();
                else {
                    command = config.createCommand().cloneCommand();
                }
                commands.add(command);
            }
        return commands;
    }

    private boolean checkFollow(List<KeyValueStore> params, String keyWord) {
        if (CollectionUtils.isEmpty(params)) {
            return false;
        }
        for (KeyValueStore kvs : params) {
            if ((keyWord.equalsIgnoreCase(kvs.getName())) && ("true".equalsIgnoreCase((String) kvs.getValue()))) {
                return true;
            }
        }
        return false;
    }

    public Object clone() {
        DSLCommandConfig dslCommandConfig = null;
        dslCommandConfig = (DSLCommandConfig) super.clone();
        dslCommandConfig.params = CloneUtil.cloneKeyValueStore(this.params);
        return dslCommandConfig;
    }
}
